home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / others / ole_101.zip / PATRON.ZIP / PATRON.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  18KB  |  626 lines

  1. /*
  2.  * PATRON.C
  3.  *
  4.  * Basic Windows application code, nothing specific to do with
  5.  * OLE except directing various menu commands to function in other
  6.  * modules that demonstrate the specific OLE library calls.
  7.  *
  8.  * Copyright(c) Microsoft Corp. 1992 All Rights Reserved
  9.  *
  10.  */
  11.  
  12. #include <windows.h>
  13. #include <ole.h>
  14. #include <shellapi.h>
  15. #include "oclient.h"
  16. #include "blackbox.h"
  17. #include "patron.h"
  18.  
  19.  
  20.  
  21. /*
  22.  * Array of pointers to strings loaded from the resource file.
  23.  * Pointers can be near since we'll use LocalAlloc for
  24.  * the string space.
  25.  */
  26.  
  27. char NEAR   *rgpsz[CSTRINGS];
  28.  
  29. //Global variable block.
  30. GLOBALS     stGlobals;
  31. LPGLOBALS   pGlob=&stGlobals;
  32.  
  33. //Pointer to OLE information, passed to OLE-specific functions
  34. LPDOCUMENT    pDoc;
  35.  
  36.  
  37.  
  38.  
  39. /*
  40.  * WinMain
  41.  *
  42.  * Purpose:
  43.  *  Main entry point of application.   Should register the app class
  44.  *  if a previous instance has not done so and do any other one-time
  45.  *  initializations.
  46.  *
  47.  * Parameters:
  48.  *  See Windows SDK Guide to Programming, page 2-3
  49.  *
  50.  * Return Value:
  51.  *  Value to return to Windows--termination code.
  52.  *
  53.  */
  54.  
  55. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  56.                     LPSTR lpszCmdLine, int nCmdShow)
  57.     {
  58.     HWND        hWnd;
  59.     MSG         msg;
  60.  
  61.     pGlob->hInst=hInstance;
  62.     pGlob->pszCmdLine=lpszCmdLine;
  63.  
  64.     if (!FApplicationInit(pGlob, hPrevInstance))
  65.         {
  66.         FApplicationExit(pGlob);
  67.         return FALSE;
  68.         }
  69.  
  70.     //Make hWnd available to everyone by placing it in pGlob
  71.     hWnd=CreateWindow(rgpsz[IDS_CLASSPATRON], rgpsz[IDS_CAPTION],
  72.                       WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW,
  73.                       CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
  74.                       NULL, NULL, hInstance, NULL);
  75.  
  76.     if (NULL==pGlob->hWnd)
  77.         {
  78.         FApplicationExit(pGlob);
  79.         return FALSE;
  80.         }
  81.  
  82.     //Give the window handle and message process functions to the OLE code.
  83.     pDoc->hWnd=pGlob->hWnd;
  84.     PDocumentMsgProcSet(pDoc, FMessageProcess);
  85.     PDocumentBackgroundProcSet(pDoc, NULL);
  86.  
  87.     ShowWindow(pGlob->hWnd, nCmdShow);
  88.     UpdateWindow(pGlob->hWnd);
  89.     FDirtySet(FALSE);
  90.  
  91.     //Make hAccel available to MessageProcess by placing it in pGlob
  92.     pGlob->hAccel=LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATORS));
  93.  
  94.     while (GetMessage(&msg, NULL, 0,0 ))
  95.         FMessageProcess(&msg);
  96.  
  97.     FApplicationExit(pGlob);
  98.     return msg.wParam;
  99.     }
  100.  
  101.  
  102.  
  103. /*
  104.  * FMessageProcess
  105.  *
  106.  * Purpose:
  107.  *  Simply calls TranslateAccelerator, TranslateMessage, and
  108.  *  DispatchMessage.  We have this in a separate function so
  109.  *  the FOLEReleaseWait function in OLEOBJ.C can call this separately.
  110.  *  That way, FOLEReleaseWait does not need to reference pGlob->hWnd
  111.  *  or pGlob->hAccel like we do here.
  112.  *
  113.  * Parameters:
  114.  *  pMsg            LPMSG to a message loaded from Get/PeekMessage.
  115.  *
  116.  * Return Value:
  117.  *  BOOL            TRUE always.
  118.  */
  119.  
  120. BOOL FAR PASCAL FMessageProcess(LPMSG pMsg)
  121.     {
  122.     if (!TranslateAccelerator(pGlob->hWnd, pGlob->hAccel, pMsg))
  123.         {
  124.         TranslateMessage(pMsg);
  125.         DispatchMessage(pMsg);
  126.         }
  127.  
  128.     return TRUE;
  129.     }
  130.  
  131.  
  132.  
  133.  
  134.  
  135. /*
  136.  * PatronWndProc
  137.  *
  138.  * Purpose:
  139.  *  Window class procedure.  Standard callback.
  140.  *
  141.  * Parameters:
  142.  *  The standard.
  143.  *
  144.  * Return Value:
  145.  *  The standard.
  146.  *
  147.  */
  148.  
  149. long FAR PASCAL PatronWndProc(HWND hWnd, UINT iMsg, UINT wParam, LONG lParam)
  150.     {
  151.     BOOL            fOK;
  152.     FARPROC         lpfn;
  153.     WORD            wTemp;
  154.     RECT            rc;
  155.     LPOBJECT        pObj;
  156.     WORD            wID[4];
  157.  
  158.     switch (iMsg)
  159.         {
  160.         case WM_CREATE:
  161.             //Set global variable defaults.
  162.             pGlob->hWnd=hWnd;
  163.             pGlob->hWndLastActive=NULL;
  164.  
  165.             FDirtySet(FALSE);
  166.  
  167.             //Notify Windows that we can take dragged files.
  168.             DragAcceptFiles(hWnd, TRUE);
  169.  
  170.             /*
  171.              * Load and register any initial document.  The TRUE in the
  172.              * call to FFileOpen indicates that we're doing this from
  173.              * startup and so suppresses the File Open dialog.
  174.              */
  175.             if (!FFileOpen(pGlob, pDoc, TRUE))
  176.                 PostMessage(hWnd, WM_CLOSE, 0, 0L);
  177.  
  178.             break;
  179.  
  180.  
  181.         case WM_INITMENUPOPUP:
  182.             /*
  183.              * Check for Save possibility in File menu position 0.
  184.              * In and OLE situation, this is always enabled.
  185.              */
  186.             if (0==LOWORD(lParam))
  187.                 {
  188.                 wTemp=(pGlob->fOpenFile) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED);
  189.                 EnableMenuItem((HMENU)wParam, IDM_FILESAVE, wTemp | MF_BYCOMMAND);
  190.                 }
  191.  
  192.             //Check for possibility of Paste for edit menu position 1
  193.             if (1==LOWORD(lParam))
  194.                 {
  195.                 //Create the OLE Object menu item as necessary.
  196.                 if (pGlob->hWndLastActive)
  197.                     pObj=(LPOBJECT)SendMessage(pGlob->hWndLastActive, BBM_POBJECTGET, 0, 0L);
  198.                 else
  199.                     pObj=NULL;
  200.  
  201.                 MenuOLEVerbAppend((HMENU)wParam, IVERBMENU, IDM_EDITVERBMIN, pDoc, pObj);
  202.  
  203.                 /*
  204.                  * Go enable or disable menu items as necessary.  Do OLE menu
  205.                  * items first, since OLE may disable but the application may still
  206.                  * want them enabled.
  207.                  */
  208.                 wID[0]=IDM_EDITPASTE;
  209.                 wID[1]=IDM_EDITPASTELINK;
  210.                 wID[2]=0;
  211.                 wID[3]=IDM_EDITLINKS;
  212.                 MenuOLEClipboardEnable((HMENU)wParam, pDoc, (LPWORD)wID);
  213.  
  214.                 MenuClipboardEnable((HMENU)wParam, pGlob);
  215.                 }
  216.  
  217.             break;
  218.  
  219.  
  220.         case WM_CLOSE:
  221.             if (!FFileExit(pGlob, pDoc))
  222.                 break;
  223.  
  224.             DestroyWindow(hWnd);    //Same as DefWindowProc's action.
  225.             break;
  226.  
  227.  
  228.         case WM_DESTROY:
  229.             //Turn off acceptance of dragged files.
  230.             DragAcceptFiles(hWnd, FALSE);
  231.  
  232.             PostQuitMessage(0);
  233.             break;
  234.  
  235.  
  236.         case WM_MOVE:
  237.         case WM_SIZE:
  238.             FDirtySet(TRUE);
  239.             break;
  240.  
  241.         case WM_KEYDOWN:
  242.             /*
  243.              * Activate the current object on an ENTER.  Primary verb 0
  244.              * is sent in wParam.
  245.              */
  246.             if (VK_RETURN==wParam)
  247.                 SendMessage(pGlob->hWndLastActive, BBM_VERBEXECUTE, 0, 0L);
  248.             break;
  249.  
  250.  
  251.         case WM_DROPFILES:
  252.             FCreateFromDropFiles(hWnd, (HANDLE)wParam, pDoc);
  253.             break;
  254.  
  255.  
  256.         case WM_COMMAND:
  257.             //Look for an object activation message.
  258.             if (wParam >= IDM_EDITVERBMIN && wParam <= IDM_EDITVERBMAX)
  259.                 {
  260.                 SendMessage(pGlob->hWndLastActive, BBM_VERBEXECUTE,
  261.                             wParam-IDM_EDITVERBMIN, 0L);
  262.                 break;
  263.                 }
  264.  
  265.             //If a blackbox changes activation, change our variable.
  266.             if (wParam >=1000 && BBN_ACTIVATED==HIWORD(lParam))
  267.                 {
  268.                 if (NULL!=pGlob->hWndLastActive)
  269.                     SendMessage(pGlob->hWndLastActive, WM_NCACTIVATE, FALSE, 0L);
  270.  
  271.                 pGlob->hWndLastActive=(HWND)LOWORD(lParam);
  272.                 }
  273.  
  274.             if (wParam >=1000 && (BBN_ACTIVATED!=HIWORD(lParam)))
  275.                 FDirtySet(TRUE);
  276.  
  277.  
  278.             switch (wParam)
  279.                 {
  280.                 case IDM_FILENEW:
  281.                     FFileNew(pGlob, pDoc);
  282.                     break;
  283.  
  284.  
  285.                 case IDM_FILEOPEN:
  286.                     FFileOpen(pGlob, pDoc, FALSE);
  287.                     break;
  288.  
  289.  
  290.                 case IDM_FILESAVE:
  291.                     FFileSave(pGlob, pDoc, FALSE);
  292.                     break;
  293.  
  294.  
  295.                 case IDM_FILESAVEAS:
  296.                     fOK=FFileSaveAs(pGlob, pDoc);
  297.                     return MAKELONG(fOK, 0);
  298.  
  299.  
  300.                 case IDM_FILEEXIT:
  301.                     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  302.                     break;
  303.  
  304.  
  305.                 case IDM_EDITCUT:
  306.                     FEditCut(pGlob);
  307.                     break;
  308.  
  309.                 case IDM_EDITCOPY:
  310.                     FEditCopy(pGlob, FALSE);
  311.                     break;
  312.  
  313.                 case IDM_EDITPASTE:
  314.                 case IDM_EDITPASTELINK:
  315.                     fOK=(IDM_EDITPASTELINK==wParam);
  316.  
  317.                     FEditPaste(pGlob, fOK, pDoc);
  318.                     break;
  319.  
  320.                 case IDM_EDITLINKS:
  321.                     if (FOLELinksEdit(hWnd, pGlob->hInst, pDoc))
  322.                         FDirtySet(TRUE);
  323.                     break;
  324.  
  325.                 case IDM_EDITINSERTOBJECT:
  326.                     FEditInsertObject(hWnd, pGlob->hInst, pDoc);
  327.                     break;
  328.  
  329.  
  330.                 case IDM_EDITCONVERTTOSTATIC:
  331.                     FEditConvertToStatic(pGlob, pDoc);
  332.                     break;
  333.  
  334.                 case IDM_EDITCLEAR:
  335.                     //Delete the active window on accelerator or menu command.
  336.                     if (0==LOWORD(lParam))
  337.                         WindowDelete(pGlob->hWndLastActive, hWnd);
  338.                     else
  339.                         //Delete the provided window.
  340.                         WindowDelete((HWND)LOWORD(lParam), hWnd);
  341.  
  342.                     FDirtySet(TRUE);
  343.                     break;
  344.  
  345.  
  346.                 case IDM_EDITCLEARALL:
  347.                     //Release all objects and wait for each to receive OLE_RELEASE.
  348.                     pDoc->cWait=0;
  349.                     FObjectsEnumerate(pDoc, FEnumClearAll, 0L);
  350.                     FOLEReleaseWait(TRUE, pDoc, NULL);
  351.  
  352.                     pGlob->hWndLastActive=NULL;
  353.  
  354.                     FDirtySet(TRUE);
  355.                     wTemp=WIDGetNext(TRUE);
  356.                     PRectGetNext(&rc, TRUE);
  357.                     break;
  358.  
  359.  
  360.                 case IDM_HELPABOUT:
  361.                     lpfn=MakeProcInstance(AboutProc, pGlob->hInst);
  362.                     DialogBox(pGlob->hInst, MAKEINTRESOURCE(IDD_ABOUT),
  363.                               pGlob->hWnd, lpfn);
  364.                     FreeProcInstance(lpfn);
  365.                     break;
  366.                 }
  367.  
  368.         default:
  369.             return (DefWindowProc(hWnd, iMsg, wParam, lParam));
  370.         }
  371.  
  372.     return 0L;
  373.     }
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381. /*
  382.  * FEnumClearAll
  383.  *
  384.  * Purpose:
  385.  *  Deletes an object window and calls OleDelete.  When OleDelete
  386.  *  returns OLE_WAIT_FOR_RELEASE, we increment pDoc->cWait so the
  387.  *  function starting the enumeration can call FOLEReleaseWait once
  388.  *  for all objects.
  389.  *
  390.  * Parameters:
  391.  *  pDoc            LPDOCUMENT to the owner of the objects.
  392.  *  pObj            LPOBJECT of the object to delete.
  393.  *  dw              DWORD for extra data, unused.
  394.  *
  395.  * Return Value:
  396.  *  BOOL            TRUE, indicates to continue enumeration.
  397.  */
  398.  
  399. BOOL FAR PASCAL FEnumClearAll(LPDOCUMENT pDoc, LPOBJECT pObj, DWORD dw)
  400.     {
  401.     HWND            hWnd;
  402.     OLESTATUS       os;
  403.  
  404.     //Get the window we stored in this object.
  405.     hWnd=(HWND)pObj->hData;
  406.  
  407.     //Delete before destroying the window to insure the data is still around.
  408.     os=OleDelete(pObj->pObj);
  409.  
  410.     /*
  411.      * We may have already released objects in which case we'll see
  412.      * OLE_ERROR_OBJECT.
  413.      */
  414.     if (OLE_ERROR_OBJECT!=os)
  415.         OsError(os, pDoc, pObj, FALSE);
  416.  
  417.     pObj->hData=NULL;
  418.     DestroyWindow(hWnd);
  419.     return TRUE;
  420.     }
  421.  
  422.  
  423.  
  424.  
  425. /*
  426.  * WindowDelete
  427.  *
  428.  * Purpose:
  429.  *  Deletes an object window, including calling OleDelete and activating
  430.  *  the next window if one exists.
  431.  *
  432.  * Parameters:
  433.  *  hWnd            HWND to destroy.
  434.  *  hWndParent      HWND of the parent of hWnd.
  435.  *
  436.  * Return Value:
  437.  *  None
  438.  */
  439.  
  440. void FAR PASCAL WindowDelete(HWND hWnd, HWND hWndParent)
  441.     {
  442.     HWND            hWndNext;
  443.     HWND            hWndPrev;
  444.     HWND            hWndT;
  445.     LPOBJECT        pObj;
  446.     OLESTATUS       os;
  447.  
  448.     /*
  449.      * Destroy the given window and activate another, which is either
  450.      * the next window in the list from the one being destroyed, the previous
  451.      * window, or the first window in the list, if it still exists.
  452.      */
  453.  
  454.     hWndNext=GetWindow(hWnd, GW_HWNDNEXT);
  455.     hWndPrev=GetWindow(hWnd, GW_HWNDPREV);
  456.  
  457.     //Logic to determine next window to activate.
  458.     hWndT=hWndNext;
  459.  
  460.     if (NULL==hWndT)
  461.         hWndT=hWndPrev;
  462.  
  463.     if (NULL==hWndT)
  464.         hWndT=GetWindow(hWndParent, GW_CHILD);
  465.  
  466.     pObj=(LPOBJECT)SendMessage(hWnd, BBM_POBJECTGET, 0, 0L);
  467.  
  468.     os=OleDelete(pObj->pObj);
  469.     os=OsError(os, pDoc, pObj, TRUE);
  470.  
  471.     if (hWndT==hWnd)
  472.         hWndT=NULL;
  473.  
  474.     DestroyWindow(hWnd);
  475.  
  476.     //Activate the new first active window.
  477.     pGlob->hWndLastActive=NULL;
  478.  
  479.     if (NULL!=hWndT)
  480.         {
  481.         BringWindowToTop(hWndT);
  482.         SendMessage(hWndT, WM_NCACTIVATE, TRUE, 0L);
  483.         }
  484.  
  485.     return;
  486.     }
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494. /*
  495.  * AboutProc
  496.  *
  497.  * Purpose:
  498.  *  Dialog procedure for the omnipresent About box.
  499.  *
  500.  * Parameters:
  501.  *  The standard.
  502.  *
  503.  * Return Value:
  504.  *  The value to be returned through the DialogBox call that
  505.  *  created the dialog.
  506.  *
  507.  */
  508.  
  509. BOOL FAR PASCAL AboutProc(HWND hDlg, UINT iMsg, UINT wParam, LONG lParam)
  510.     {
  511.     switch (iMsg)
  512.         {
  513.         case WM_INITDIALOG:
  514.             return TRUE;
  515.  
  516.         case WM_COMMAND:
  517.             switch (wParam)
  518.                 {
  519.                 case IDOK:
  520.                     EndDialog(hDlg, TRUE);
  521.                 }
  522.             break;
  523.         }
  524.     return FALSE;
  525.     }
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532. /*
  533.  * ClientCallback
  534.  *
  535.  * Purpose:
  536.  *  OLECLI calls this function for various events in the server
  537.  *  application:
  538.  *
  539.  *      OLE_CHANGED:        The object was changed in the server application.
  540.  *                          The client repaints the object to show the changes.
  541.  *
  542.  *      OLE_CLOSED:         (Embedded objects only)  The server that was
  543.  *                          editing the embedded object closed.
  544.  *
  545.  *      OLE_QUERY_PAINT:    OLECLI is processing a lengthy draw operation on
  546.  *                          an object, so this notification allows the client
  547.  *                          application to stop drawing if desired.
  548.  *
  549.  *      OLE_QUERY_RETRY:    An OLE function call in the client returned
  550.  *                          OLE_BUSY.  This notification allows the app
  551.  *                          to attempt to retry the operation or terminate it.
  552.  *
  553.  *      OLE_RELEASE:        An asynchronous operation has finished and other
  554.  *                          actions can be taken on the single object affected.
  555.  *
  556.  *      OLE_RENAMED:        (Linked objects only) Informs the client that a
  557.  *                          linked object was renamed allowing the client to
  558.  *                          update private data structures.  All information
  559.  *                          in OLECLI is already updated.
  560.  *
  561.  *      OLE_SAVED:          Informs the client that an object was saved
  562.  *                          (linked object) or updated (embedded objects).
  563.  *                          The client should update and repaint the object.
  564.  *
  565.  * Parameters:
  566.  *  pObj            LPOBJECT to the object structure given as the LPOLECLIENT
  567.  *                  parameter in various OleCreate calls.  This has all our
  568.  *                  object information.
  569.  *  wCode           OLE_NOTIFICATION code informing the client of the action
  570.  *                  taken that affects the object.
  571.  *  pOLEObj         LPOLEOBJECT providing a reference to the object's VTBL.
  572.  *
  573.  * Return Value:
  574.  *  int             The return value is irrelevant except when wCode
  575.  *                  contains OLE_QUERY_PAINT and OLE_QUERY_RETRY, where
  576.  *                  a TRUE means continue the operation and FALSE means
  577.  *                  abort the operation.
  578.  */
  579.  
  580. int FAR PASCAL ClientCallback(LPOBJECT pObj, OLE_NOTIFICATION wCode,
  581.                               LPOLEOBJECT pOLEObj)
  582.     {
  583.     switch (wCode)
  584.         {
  585.         case OLE_CLOSED:    //Server closed for an embedded object.
  586.             SetFocus(pGlob->hWnd);
  587.             pObj->fOpen=FALSE;
  588.  
  589.             if (pObj->hData)
  590.                 PostMessage((HWND)pObj->hData, BBM_OBJECTNOTIFY, wCode, (LONG)pObj);
  591.             break;
  592.  
  593.         case OLE_SAVED:
  594.         case OLE_CHANGED:
  595.         case OLE_RENAMED:   //Server Save As on a linked object.
  596.             if (pObj->hData)
  597.                 PostMessage((HWND)pObj->hData, BBM_OBJECTNOTIFY, wCode, (LONG)pObj);
  598.             break;
  599.  
  600.         case OLE_RELEASE:
  601.             /*
  602.              * When an asynchronous operation has completed, OLECLI
  603.              * will tell us with OLE_RELEASE.  We set pObj->fRelease to
  604.              * exit the loop if we're waiting for a single object, or
  605.              * decrement pObj->pDoc->cWait which might exit the loop waiting
  606.              * for all objects.
  607.              */
  608.             pObj->fRelease=TRUE;
  609.             pObj->pDoc->cWait--;
  610.             break;
  611.  
  612.         case OLE_QUERY_RETRY:
  613.             //OLECLI asks if we can continue retrying to get the message through.
  614.             break;
  615.              
  616.         case OLE_QUERY_PAINT:
  617.             //OLECLI asks if we should continue repainting.
  618.             return TRUE;
  619.  
  620.         default:
  621.             break;
  622.         }
  623.  
  624.     return 0;
  625.     }
  626.